package com.zhiyun.yycall.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import com.gzit.adapter.CommonListAdapter;
import com.gzit.common.async.LoadingAsyncTask;
import com.gzit.store.StoreManager;
import com.gzit.utils.AndroidUtils;
import com.gzit.utils.StringUtils;
import com.zhiyun.common.DialogItem;
import com.zhiyun.common.DialogItemListAdapter;
import com.zhiyun.store.CallHistory;
import com.zhiyun.store.CallLogItem;
import com.zhiyun.trace.TraceActivity;
import com.zhiyun.yycall.Config;
import com.zhiyun.yycall.R;
import com.zhiyun.yycall.YYCallController;

public class CallActivity extends TraceActivity {

	private int[] btnIDs = new int[] { R.id.key0, R.id.key1, R.id.key2,
			R.id.key3, R.id.key4, R.id.key5, R.id.key6, R.id.key7, R.id.key8,
			R.id.key9, R.id.key_star, R.id.key_number_sign, R.id.key_call,
			R.id.key_del, R.id.key_control, R.id.key_add };

	private CallActivity that = this;

	private TextView callNoTV;

	private CallAdapter adapter;
	private ListView listview;

	private BroadcastReceiver receiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			loadHistory();
		}
	};

	class CallAdapter extends CommonListAdapter<CallHistory> {

		public CallAdapter(Context context) {
			super(context);
			this.setItemLayout(R.layout.call_history_item);
		}

		@Override
		protected void render(CallHistory item, View view, int position) {

			TextView callNo = (TextView) view.findViewById(R.id.call_no);
			TextView callTotal = (TextView) view.findViewById(R.id.call_total);
			TextView callTime = (TextView) view.findViewById(R.id.call_time);
			TextView callName = (TextView) view.findViewById(R.id.call_name);

			callNo.setText(item.targetNo);
			callTotal.setText("(" + item.callTotal + ")");
			callTime.setText(item.callTimeDesc);
			callName.setText(StringUtils.isBlank(item.callName) ? item.targetNo
					: item.callName);

		}

	}

	private OnClickListener listener = new OnClickListener() {

		@Override
		public void onClick(View v) {

			String callNo = callNoTV.getText().toString();

			switch (v.getId()) {

			case R.id.key0:

				callNoTV.setText(callNo + "0");

				break;
			case R.id.key1:
				callNoTV.setText(callNo + "1");
				break;
			case R.id.key2:
				callNoTV.setText(callNo + "2");
				break;
			case R.id.key3:
				callNoTV.setText(callNo + "3");
				break;
			case R.id.key4:
				callNoTV.setText(callNo + "4");
				break;
			case R.id.key5:
				callNoTV.setText(callNo + "5");
				break;
			case R.id.key6:
				callNoTV.setText(callNo + "6");
				break;
			case R.id.key7:
				callNoTV.setText(callNo + "7");
				break;
			case R.id.key8:
				callNoTV.setText(callNo + "8");
				break;
			case R.id.key9:
				callNoTV.setText(callNo + "9");
				break;
			case R.id.key_star:
				callNoTV.setText(callNo + "*");
				break;
			case R.id.key_number_sign:
				callNoTV.setText(callNo + "#");
				break;

			case R.id.key_del:
				if (!StringUtils.isBlank(callNo)) {
					callNoTV.setText(callNo.subSequence(0, callNo.length() - 1));
				}
				break;
			case R.id.key_control:
				switchKeyboard();

				break;
			case R.id.key_call:
				String phoneNo = callNo.toString();
				if (StringUtils.isBlank(phoneNo)) {
					AndroidUtils.toastShort("请输入拨号号码");
					return;

				}

				phoneNo = phoneNo.trim();
				trace("call_from_keyboard");
				startCall(phoneNo);
				break;
			case R.id.invite_container:
				gotoInviteActivity();
				break;

			case R.id.key_add:
				addToLocal();
				break;

			}

		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.call_activity);

		callNoTV = (TextView) this.findViewById(R.id.phone_no);
		adapter = new CallAdapter(this);
		listview = (ListView) this.findViewById(R.id.listview);
		listview.setAdapter(adapter);
		listview.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				hideKeybaord();
				return false;
			}
		});

		for (int id : btnIDs) {
			this.findViewById(id).setOnClickListener(listener);
		}

		this.findViewById(R.id.invite_container).setOnClickListener(listener);

		this.loadHistory();

		this.listview.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {

				CallHistory history = adapter.getItem(position);
				startCall(history.targetNo);
				trace("call_from_history_list");

			}
		});

		// test...
		// startTest();

	}

	private void startTest() {

		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {

			@Override
			public void run() {

				listview.post(new Runnable() {

					@Override
					public void run() {
						// YYCallScreen.getInstance().show(that, "弹窗性能测试");

					}
				});

				try {

					Thread.sleep(2 * 1000);

				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				listview.post(new Runnable() {

					@Override
					public void run() {
						// YYCallScreen.getInstance().hide();

					}
				});

			}
		}, 1000, 3 * 1000);

	}

	private void gotoInviteActivity() {
		Intent intent = new Intent();
		intent.setClass(this, InviteActivity.class);
		this.startActivity(intent);

	}

	private void startCall(final String targetNo) {

		// 网络不可用，提示用户是否切换到正常拨号形式
		if (!AndroidUtils.System.isNetworkAvailable()) {
			AndroidUtils.Dialog.confirm(this, "云之呼温馨提示",
					"当前网络不可用，是否切换回【系统拨号】模式？",
					new DialogInterface.OnClickListener() {

						@Override
						public void onClick(DialogInterface dialog, int which) {
							YYCallController.startNormalCall(CallActivity.this,
									targetNo);
							finish();

						}
					});

			return;

		}

		YYCallController.createController(this).startCallback(targetNo);

	}

	// TD:这不是个高效的算法，直接更新数据源，避免重新查库
	private void loadHistory() {

		new AsyncTask<String, Integer, List<CallHistory>>() {

			@Override
			protected void onPostExecute(List<CallHistory> result) {
				super.onPostExecute(result);
				if (result == null) {
					return;
				}
				that.adapter.reload(result);
			}

			@Override
			protected List<CallHistory> doInBackground(String... params) {

				List<CallLogItem> callLogItems = null;
				List<CallHistory> historyRecords = null;
				try {
					callLogItems = StoreManager.findAll(CallLogItem.DUMY,
							"callTime DESC limit 0,500");

					Map<String, CallHistory> historyMapper = new HashMap<String, CallHistory>();
					for (CallLogItem item : callLogItems) {
						String targetNo = item.targetNo;
						CallHistory history = historyMapper.get(targetNo);
						if (history == null) {
							history = new CallHistory();
							historyMapper.put(targetNo, history);
						}
						history.items.add(item);
					}

					historyRecords = new LinkedList<CallHistory>(
							historyMapper.values());

					for (CallHistory history : historyRecords) {
						history.evalute();
					}
					historyMapper.clear();
					Collections.sort(historyRecords, CallHistory.COMPARATOR);

				} catch (Exception e) {
					e.printStackTrace();
				}

				return historyRecords;
			}
		}.execute("");

	}

	protected void onResume() {
		super.onResume();
		// 接收新拨号的历史记录
		IntentFilter filter = new IntentFilter();
		filter.addAction(Config.ACTION_CALLHISTORY);
		this.registerReceiver(receiver, filter);

	}

	@Override
	protected void onPause() {
		super.onPause();

	}

	@Override
	protected void onStop() {
		super.onStop();

	}

	// /////////////////////////////////////////////////////////
	private List<MatchedContactItem> matchedContacts;

	private void addToLocal() {

		final String phone = callNoTV.getText().toString();
		if (StringUtils.isBlank(phone)) {
			AndroidUtils.toastShort("请输入要保存到系统通讯录的电话号码");
			return;

		}

		new LoadingAsyncTask<String, String, Boolean>(this) {

			@Override
			protected Boolean doInBackground(String... params) {

				try {
					matchedContacts = findContactAlreadyInContacts(phone);
				} catch (Exception e) {
					return false;

				}
				return true;
			}

			protected void onPostExecute(Boolean result) {
				super.onPostExecute(result);
				if (result) {
					if (matchedContacts.isEmpty()) {
						createNewContactInLocal(phone);
						return;
					}

					// 本地通讯录中已经存在该联系人
					if (matchedContacts.size() == 1) {// 只有一个重复的
						showDialog(OPERATE_ON_STORE_TO_LOCAL_SINGLE_DIALOG);
					} else // 有多个重复时
					{
						showDialog(OPERATE_ON_STORE_TO_LOCAL_MULTI_DIALOG);
					}

				}

			};

		}.execute("");

	}

	// 与本地通讯录融合
	private void mergeContactToLocal(MatchedContactItem item) {
		Log.i("Contacts:", "merge to:" + item.toString());

		Uri editUri = Uri.withAppendedPath(
				ContactsContract.Contacts.CONTENT_URI, item.contactId);
		Intent saveIntent = new Intent(Intent.ACTION_EDIT, editUri);

		List<String> localPhones = new LinkedList<String>();

		Cursor contactCursor = null;
		Cursor phoneCursor = null;

		ContentResolver cr = this.getContentResolver();
		try {

			contactCursor = cr.query(editUri, null, null, null, null);
			while (contactCursor.moveToNext()) {// 找到对应联系人记录
				String id = contactCursor.getString(contactCursor
						.getColumnIndex(ContactsContract.Contacts._ID));

				// 获得所有的电话号码
				if (Integer
						.parseInt(contactCursor.getString(contactCursor
								.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
					phoneCursor = cr.query(
							ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
							null,
							ContactsContract.CommonDataKinds.Phone.CONTACT_ID
									+ " = ?", new String[] { id }, null);

					while (phoneCursor.moveToNext()) {
						String localPhone = phoneCursor
								.getString(phoneCursor
										.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
						localPhone = localPhone.replace("-", "");
						localPhones.add(localPhone);

					}

				}

			}
		}

		finally {

			if (contactCursor != null) {
				contactCursor.close();
			}

			if (phoneCursor != null) {
				phoneCursor.close();
			}

		}

		saveIntent.putExtra(ContactsContract.Intents.Insert.SECONDARY_PHONE,
				item.phone);

		this.startActivity(saveIntent);

	}

	// 在本地通讯录中创建新的通讯录记录
	private void createNewContactInLocal(String phone) {

		Intent saveIntent = new Intent(Intent.ACTION_INSERT,
				ContactsContract.Contacts.CONTENT_URI);
		saveIntent.putExtra(ContactsContract.Intents.Insert.PHONE, phone);
		this.startActivity(saveIntent);
		this.trace("store");

	}

	private List<MatchedContactItem> findContactAlreadyInContacts(String mobile) {

		// 匹配到号码的联系人记录
		List<MatchedContactItem> matchedPhoneContacts = new ArrayList<MatchedContactItem>();

		// 没匹配到号码，但是匹配到姓名的联系人
		List<MatchedContactItem> matchedNameContacts = new ArrayList<MatchedContactItem>();
		ContentResolver cr = getContentResolver();
		Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
				null, null, null);
		try {
			// 没找到通讯录
			if (cur == null || cur.getCount() <= 0) {
				return matchedPhoneContacts;
			}

			while (cur.moveToNext()) {

				String id = cur.getString(cur
						.getColumnIndex(ContactsContract.Contacts._ID));

				// 名称
				String name = cur
						.getString(cur
								.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

				// 电话号码
				if (Integer
						.parseInt(cur.getString(cur
								.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
					// Query phone here. Covered next
					Cursor pCur = cr.query(
							ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
							null,
							ContactsContract.CommonDataKinds.Phone.CONTACT_ID
									+ " = ?", new String[] { id }, null);

					try {

						while (pCur.moveToNext()) {

							String localPhone = pCur
									.getString(pCur
											.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
							localPhone = localPhone.replace("-", "");
							if (mobile.equals(localPhone)) {// 本地已存在同样的手机号码
								MatchedContactItem co = new MatchedContactItem();
								co.name = name;
								co.phone = localPhone;
								co.contactId = id;
								matchedPhoneContacts.add(co);
								break;

							}

						}

					} finally {
						if (pCur != null) {
							pCur.close();
						}
					}

				}

			}
		} finally {
			if (cur != null) {
				cur.close();
			}

		}

		// 有匹配到号码的联系人，则忽略匹配到姓名的
		return matchedPhoneContacts.isEmpty() ? matchedNameContacts
				: matchedPhoneContacts;

	}

	private static final int OPERATE_ON_STORE_TO_LOCAL_SINGLE_DIALOG = 1;
	private static final int OPERATE_ON_STORE_TO_LOCAL_MULTI_DIALOG = 2;
	private static final int OPERATE_ON_STORE_TO_LOCAL_MULTI_LIST_DIALOG = 3;

	protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
		// super.onPrepareDialog(id, dialog, args);
		super.onPrepareDialog(id, dialog);

		switch (id) {
		case OPERATE_ON_STORE_TO_LOCAL_SINGLE_DIALOG:
			dialog.setTitle(matchedContacts.get(0).getMessage());
			break;

		case OPERATE_ON_STORE_TO_LOCAL_MULTI_DIALOG:

			int phoneExistCount = 0;
			MatchedContactItem phoneExistItem = null;
			for (MatchedContactItem item : matchedContacts) {
				if (item.phoneMatched) {
					phoneExistCount++;
					phoneExistItem = item;
				}
			}

			if (phoneExistCount == 0) {
				dialog.setTitle(String.format("本地已存在联系人%s(多个)",
						matchedContacts.get(0).name));
			} else {
				dialog.setTitle(String.format("本地已存在联系人号码%s(多个)",
						phoneExistItem.phone));
			}

			break;

		case OPERATE_ON_STORE_TO_LOCAL_MULTI_LIST_DIALOG:
			dialog.setTitle("选择要添加到的现有联系人");
			break;
		}
	}

	private Dialog createStoreSingleContactDialog() {
		Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("选择");
		List<DialogItem> menu = new ArrayList<DialogItem>();
		menu.add(new DialogItem("创建新的联系人"));
		menu.add(new DialogItem("添加到现有联系人"));

		DialogItemListAdapter adapter = new DialogItemListAdapter(this, menu);
		builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {

				switch (which) {
				case 0:

					createNewContactInLocal(callNoTV.getText().toString());
					break;
				case 1:
					mergeContactToLocal(matchedContacts.get(0));
					break;
				default:

				}

			}
		});

		return builder.create();
	}

	private Dialog createStoreMultiContactDialog() {
		Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("选择");
		List<DialogItem> menu = new ArrayList<DialogItem>();
		menu.add(new DialogItem("创建新的联系人"));
		menu.add(new DialogItem("添加到现有联系人"));

		DialogItemListAdapter adapter = new DialogItemListAdapter(this, menu);
		builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {

				switch (which) {
				case 0:
					createNewContactInLocal(callNoTV.getText().toString());
					break;
				case 1:
					showDialog(OPERATE_ON_STORE_TO_LOCAL_MULTI_LIST_DIALOG);
					break;
				default:

				}

			}
		});

		return builder.create();
	}

	private Dialog createStoreMultiContactsListDialog() {
		Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("选择");
		List<DialogItem> menu = new ArrayList<DialogItem>();
		for (MatchedContactItem item : this.matchedContacts) {
			String desc = "%s(%s)";
			menu.add(new DialogItem(item.phoneMatched ? String.format(desc,
					item.phone, item.name) : String.format(desc, item.name,
					item.phone)));
		}

		DialogItemListAdapter adapter = new DialogItemListAdapter(this, menu);
		builder.setAdapter(adapter, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {

				mergeContactToLocal(matchedContacts.get(which));

			}
		});

		return builder.create();

	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case OPERATE_ON_STORE_TO_LOCAL_SINGLE_DIALOG:
			return createStoreSingleContactDialog();
		case OPERATE_ON_STORE_TO_LOCAL_MULTI_DIALOG:
			return createStoreMultiContactDialog();
		case OPERATE_ON_STORE_TO_LOCAL_MULTI_LIST_DIALOG:
			return createStoreMultiContactsListDialog();

		}

		return super.onCreateDialog(id);
	}

	private void hideKeybaord() {
		View keyboard = that.findViewById(R.id.keyborad);
		keyboard.setVisibility(View.GONE);
		ImageButton controlView = (ImageButton) this
				.findViewById(R.id.key_control);
		controlView.setBackgroundResource(R.drawable.key_up);
	}

	private void switchKeyboard() {
		View keyboard = that.findViewById(R.id.keyborad);
		keyboard.setVisibility(keyboard.getVisibility() == View.VISIBLE ? View.GONE
				: View.VISIBLE);
		ImageButton controlView = (ImageButton) this
				.findViewById(R.id.key_control);
		controlView
				.setBackgroundResource(keyboard.getVisibility() == View.VISIBLE ? R.drawable.key_down
						: R.drawable.key_up);
	}

	// 查看在本地通讯录中是否已经存在相应的通讯记录
	static class MatchedContactItem {
		String name;
		String phone;
		String contactId;
		boolean phoneMatched;

		public String getMessage() {
			if (phoneMatched) {
				return String.format("本地已存在联系人号码%s(%s)", phone, name);
			}
			return String.format("本地已存在联系人%s", name, phone);

		}

		public String toString() {
			return "name:" + name + " phone:" + phone + " phoneMatched:"
					+ phoneMatched + " contactId:" + contactId;
		}

	}

}
